#include "ListObject.hpp"
#include "../../base/Defind.hpp"

inline  
auto split_command_value(std::string& command, std::string& v1, std::string& v2) -> void
{
    std::string &tmp = v1;
    // initialize the key and value
    for (char c : command)
    {
        if (c == ' ')
        {
            tmp = v2;
            continue;
        }
        tmp += c;
    }
}

using namespace DBServer::Database;
using CallBack = std::function<void(ListObject&, CommandRequest&&, CommandRespond&)>;

void ListObject::command_excute(CommandRespond& crp, CommandRequest&& crq, com_func_t& cft) 
{
    cb_table[cft.second](*this, std::move(crq), crp);
}

std::unordered_map<int, CallBack> ListObject::cb_table([]{
    std::unordered_map<int, CallBack> temp;
    
    temp[COMMAND_LPUSH] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        auto ret = lo.lpush(std::move(crq.command[COMMAND_VALUE]));
        crp.respond = LISTOBJECT_LEN + Translator::int_to_string(ret) + "\n";
    };

    temp[COMMAND_RPUSH] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        auto ret = lo.rpush(std::move(crq.command[COMMAND_VALUE]));
        crp.respond = LISTOBJECT_LEN + Translator::int_to_string(ret) + "\n";
    };

    temp[COMMAND_LPOP] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        auto ret = lo.lpop();
        crp.respond = ret;
    };

    temp[COMMAND_RPOP] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        auto ret = lo.rpop();
        crp.respond = ret;
    };

    temp[COMMAND_LINDEX] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        auto ret = lo.lindex(
            Translator::string_to_int(crq.command[COMMAND_VALUE]), 
            crp.respond);
        
        if (!ret)
        {
            crp.respond = LINDEX_OUT_OF_RANGE;
        }
    };

    temp[COMMAND_LLEN] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        auto ret = lo.llen();
        crp.respond = Translator::int_to_string(ret);
    };

    temp[COMMAND_LINSERT] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        std::string index{""};
        std::string new_value{""};
        // initialize the key and value
        split_command_value(crq.command[COMMAND_VALUE], index, new_value);
        auto temp_rp = new_value;
        
        auto ret = lo.linsert(Translator::string_to_int(index), std::move(new_value));

        if (ret)
        {
            crp.respond = LINSERT_SUCCESS(index, temp_rp);
        } else
        {
            crp.respond = LINSERT_FAULT;
        }
    };

    temp[COMMAND_LREMOVE] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        auto ret = lo.lremove(
                Translator::string_to_int(crq.command[COMMAND_VALUE]), crp.respond);

        if (!ret)
        {
            crp.respond = LREMOVE_FAULT;
        }
    };

    temp[COMMAND_LSET] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        std::string index{""};
        std::string new_value{""};
        // initialize the key and value
        split_command_value(crq.command[COMMAND_VALUE], index, new_value);
        auto temp_rp = new_value;
        
        auto ret = lo.lset(Translator::string_to_int(index), std::move(new_value));

        if (ret)
        {
            crp.respond = LSET_SUCCESS(index, temp_rp);
        } else
        {
            crp.respond = LSET_FAULT;
        }
    };

    temp[COMMAND_LTRIM] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        std::string begin{""};
        std::string end{""};
        // initialize the key and value
        split_command_value(crq.command[COMMAND_VALUE], begin, end);

        auto ret = lo.ltrim(Translator::string_to_int(begin), Translator::string_to_int(end));

        crp.respond =  LTRIM_NUM(Translator::int_to_string(ret));
    };

    temp[COMMAND_GET] = [](ListObject& lo, CommandRequest&& crq, CommandRespond& crp){
        crp.respond = Translator::vector_to_string_1(lo.get());
    };
    
    return temp;
}());